package net.gdface.sdk.thrift;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.Map;
import net.gdface.image.ImageErrorException;
import net.gdface.sdk.CodeInfo;
import net.gdface.sdk.FRect;
import net.gdface.sdk.FaceApi;
import net.gdface.sdk.NotFaceDetectedException;
import net.gdface.thrift.TypeTransformer;
import net.gdface.thrift.ClientFactory;

import com.facebook.swift.service.RuntimeTApplicationException;
import static com.google.common.base.Preconditions.*;

/**
 * 基于thrift/swift框架生成的client端代码提供{@link FaceApi}接口的RPC实现(线程安全)<br>
 * 转发所有{@link FaceApi}接口方法到{@link #delegate()}指定的实例<br>
 * 所有服务端抛出的{@link RuntimeException}异常被封装到{@link ServiceRuntimeException}中抛出<br>
 * Example:<br>
 * <pre>
 *        FaceApiThriftClient thriftInstance = ClientFactory
 *            .builder()
 *            .setHostAndPort("127.0.0.1",26413)
 *            .build(FaceApi.class, FaceApiThriftClient.class);
 * </pre>
 * 计算机生成代码(generated by automated tools ThriftServiceDecoratorGenerator @author guyadong)<br>
 * @author guyadong
 *
 */
public class FaceApiThriftClient implements FaceApi {
    private final ClientFactory factory;

    public ClientFactory getFactory() {
        return factory;
    }
    public FaceApiThriftClient(ClientFactory factory) {
        super();
        this.factory = checkNotNull(factory,"factory is null");
    }

    /**
     * 返回{@link net.gdface.sdk.thrift.client.FaceApi}实例
     * @return
     */
    protected net.gdface.sdk.thrift.client.FaceApi delegate() {
        return factory.applyInstance(net.gdface.sdk.thrift.client.FaceApi.class);
    }
    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("FaceApiThriftClient [factory=");
        builder.append(factory);
        builder.append(",interface=");
        builder.append(FaceApi.class.getName());
        builder.append("]");
        return builder.toString();
    }
    @Override
    public double compare2Face(byte[] imgData1,
        CodeInfo facePos1,
        byte[] imgData2,
        CodeInfo facePos2) 
        throws ImageErrorException,NotFaceDetectedException{
        net.gdface.sdk.thrift.client.FaceApi instance = delegate();
        try{
            return instance.compare2Face(imgData1,
                TypeTransformer.getInstance().to(
                    facePos1,
                    CodeInfo.class,
                    net.gdface.sdk.thrift.client.CodeInfo.class),
                imgData2,
                TypeTransformer.getInstance().to(
                    facePos2,
                    CodeInfo.class,
                    net.gdface.sdk.thrift.client.CodeInfo.class));
        }
        catch(net.gdface.sdk.thrift.client.ImageErrorException e){
            throw TypeTransformer.getInstance().to(
                    e,
                    net.gdface.sdk.thrift.client.ImageErrorException.class,
                    ImageErrorException.class);
        }
        catch(net.gdface.sdk.thrift.client.NotFaceDetectedException e){
            throw TypeTransformer.getInstance().to(
                    e,
                    net.gdface.sdk.thrift.client.NotFaceDetectedException.class,
                    NotFaceDetectedException.class);
        }
        catch(net.gdface.sdk.thrift.client.ServiceRuntimeException e){
            throw new ServiceRuntimeException(e);
        }
        finally{
            factory.releaseInstance(instance);
        }
    }
    @Override
    public double compareCode(byte[] code1,
        byte[] code2) 
        {
        net.gdface.sdk.thrift.client.FaceApi instance = delegate();
        try{
            return instance.compareCode(code1,
                code2);
        }
        catch(net.gdface.sdk.thrift.client.ServiceRuntimeException e){
            throw new ServiceRuntimeException(e);
        }
        finally{
            factory.releaseInstance(instance);
        }
    }
    @Override
    public double[] compareCodes(byte[] code1,
        CodeInfo[] codes) 
        {
        net.gdface.sdk.thrift.client.FaceApi instance = delegate();
        try{
            return TypeTransformer.getInstance().todoubleArray(
                    instance.compareCodes(code1,
                TypeTransformer.getInstance().to(
                    codes,
                    CodeInfo.class,
                    net.gdface.sdk.thrift.client.CodeInfo.class)),
                    double.class,
                    double.class);
        }
        catch(net.gdface.sdk.thrift.client.ServiceRuntimeException e){
            throw new ServiceRuntimeException(e);
        }
        catch(RuntimeTApplicationException e){
            return net.gdface.thrift.ThriftUtils.returnNull(e);
        }
        finally{
            factory.releaseInstance(instance);
        }
    }
    @Override
    public Map<CodeInfo, Double> compareFaces(byte[] code,
        byte[] imgData,
        int faceNum) 
        throws ImageErrorException,NotFaceDetectedException{
        net.gdface.sdk.thrift.client.FaceApi instance = delegate();
        try{
            return TypeTransformer.getInstance().to(
                    instance.compareFaces(code,
                imgData,
                faceNum),
                    net.gdface.sdk.thrift.client.CodeInfo.class,
                    Double.class,
                    CodeInfo.class,
                    Double.class);
        }
        catch(net.gdface.sdk.thrift.client.ImageErrorException e){
            throw TypeTransformer.getInstance().to(
                    e,
                    net.gdface.sdk.thrift.client.ImageErrorException.class,
                    ImageErrorException.class);
        }
        catch(net.gdface.sdk.thrift.client.NotFaceDetectedException e){
            throw TypeTransformer.getInstance().to(
                    e,
                    net.gdface.sdk.thrift.client.NotFaceDetectedException.class,
                    NotFaceDetectedException.class);
        }
        catch(net.gdface.sdk.thrift.client.ServiceRuntimeException e){
            throw new ServiceRuntimeException(e);
        }
        catch(RuntimeTApplicationException e){
            return net.gdface.thrift.ThriftUtils.returnNull(e);
        }
        finally{
            factory.releaseInstance(instance);
        }
    }
    @Override
    public List<Double> compareFeatures(byte[] code1,
        List<byte[]> codes) 
        {
        net.gdface.sdk.thrift.client.FaceApi instance = delegate();
        try{
            return TypeTransformer.getInstance().to(
                    instance.compareFeatures(code1,
                TypeTransformer.getInstance().to(
                    codes,
                    byte[].class,
                    byte[].class)),
                    Double.class,
                    Double.class);
        }
        catch(net.gdface.sdk.thrift.client.ServiceRuntimeException e){
            throw new ServiceRuntimeException(e);
        }
        catch(RuntimeTApplicationException e){
            return net.gdface.thrift.ThriftUtils.returnNull(e);
        }
        finally{
            factory.releaseInstance(instance);
        }
    }
    @Override
    public double detectAndCompare2Face(byte[] imgData1,
        FRect detectRect1,
        byte[] imgData2,
        FRect detectRect2) 
        throws ImageErrorException,NotFaceDetectedException{
        net.gdface.sdk.thrift.client.FaceApi instance = delegate();
        try{
            return instance.detectAndCompare2Face(imgData1,
                TypeTransformer.getInstance().to(
                    detectRect1,
                    FRect.class,
                    net.gdface.sdk.thrift.client.FRect.class),
                imgData2,
                TypeTransformer.getInstance().to(
                    detectRect2,
                    FRect.class,
                    net.gdface.sdk.thrift.client.FRect.class));
        }
        catch(net.gdface.sdk.thrift.client.ImageErrorException e){
            throw TypeTransformer.getInstance().to(
                    e,
                    net.gdface.sdk.thrift.client.ImageErrorException.class,
                    ImageErrorException.class);
        }
        catch(net.gdface.sdk.thrift.client.NotFaceDetectedException e){
            throw TypeTransformer.getInstance().to(
                    e,
                    net.gdface.sdk.thrift.client.NotFaceDetectedException.class,
                    NotFaceDetectedException.class);
        }
        catch(net.gdface.sdk.thrift.client.ServiceRuntimeException e){
            throw new ServiceRuntimeException(e);
        }
        finally{
            factory.releaseInstance(instance);
        }
    }
    @Override
    public CodeInfo[] detectAndGetCodeInfo(byte[] imgData,
        int faceNum) 
        throws ImageErrorException,NotFaceDetectedException{
        net.gdface.sdk.thrift.client.FaceApi instance = delegate();
        try{
            return TypeTransformer.getInstance().toArray(
                    instance.detectAndGetCodeInfo(imgData,
                faceNum),
                    net.gdface.sdk.thrift.client.CodeInfo.class,
                    CodeInfo.class);
        }
        catch(net.gdface.sdk.thrift.client.ImageErrorException e){
            throw TypeTransformer.getInstance().to(
                    e,
                    net.gdface.sdk.thrift.client.ImageErrorException.class,
                    ImageErrorException.class);
        }
        catch(net.gdface.sdk.thrift.client.NotFaceDetectedException e){
            throw TypeTransformer.getInstance().to(
                    e,
                    net.gdface.sdk.thrift.client.NotFaceDetectedException.class,
                    NotFaceDetectedException.class);
        }
        catch(net.gdface.sdk.thrift.client.ServiceRuntimeException e){
            throw new ServiceRuntimeException(e);
        }
        catch(RuntimeTApplicationException e){
            return net.gdface.thrift.ThriftUtils.returnNull(e);
        }
        finally{
            factory.releaseInstance(instance);
        }
    }
    @Override
    public CodeInfo detectCenterFace(byte[] imgData) 
        throws ImageErrorException,NotFaceDetectedException{
        net.gdface.sdk.thrift.client.FaceApi instance = delegate();
        try{
            return TypeTransformer.getInstance().to(
                    instance.detectCenterFace(imgData),
                    net.gdface.sdk.thrift.client.CodeInfo.class,
                    CodeInfo.class);
        }
        catch(net.gdface.sdk.thrift.client.ImageErrorException e){
            throw TypeTransformer.getInstance().to(
                    e,
                    net.gdface.sdk.thrift.client.ImageErrorException.class,
                    ImageErrorException.class);
        }
        catch(net.gdface.sdk.thrift.client.NotFaceDetectedException e){
            throw TypeTransformer.getInstance().to(
                    e,
                    net.gdface.sdk.thrift.client.NotFaceDetectedException.class,
                    NotFaceDetectedException.class);
        }
        catch(net.gdface.sdk.thrift.client.ServiceRuntimeException e){
            throw new ServiceRuntimeException(e);
        }
        catch(RuntimeTApplicationException e){
            return net.gdface.thrift.ThriftUtils.returnNull(e);
        }
        finally{
            factory.releaseInstance(instance);
        }
    }
    @Override
    public CodeInfo[] detectFace(byte[] imgData) 
        throws ImageErrorException{
        net.gdface.sdk.thrift.client.FaceApi instance = delegate();
        try{
            return TypeTransformer.getInstance().toArray(
                    instance.detectFace(imgData),
                    net.gdface.sdk.thrift.client.CodeInfo.class,
                    CodeInfo.class);
        }
        catch(net.gdface.sdk.thrift.client.ImageErrorException e){
            throw TypeTransformer.getInstance().to(
                    e,
                    net.gdface.sdk.thrift.client.ImageErrorException.class,
                    ImageErrorException.class);
        }
        catch(net.gdface.sdk.thrift.client.ServiceRuntimeException e){
            throw new ServiceRuntimeException(e);
        }
        catch(RuntimeTApplicationException e){
            return net.gdface.thrift.ThriftUtils.returnNull(e);
        }
        finally{
            factory.releaseInstance(instance);
        }
    }
    @Override
    public CodeInfo[] getCodeInfo(byte[] imgData,
        int faceNum,
        CodeInfo[] facePos) 
        throws NotFaceDetectedException{
        net.gdface.sdk.thrift.client.FaceApi instance = delegate();
        try{
            return TypeTransformer.getInstance().toArray(
                    instance.getCodeInfo(imgData,
                faceNum,
                TypeTransformer.getInstance().to(
                    facePos,
                    CodeInfo.class,
                    net.gdface.sdk.thrift.client.CodeInfo.class)),
                    net.gdface.sdk.thrift.client.CodeInfo.class,
                    CodeInfo.class);
        }
        catch(net.gdface.sdk.thrift.client.NotFaceDetectedException e){
            throw TypeTransformer.getInstance().to(
                    e,
                    net.gdface.sdk.thrift.client.NotFaceDetectedException.class,
                    NotFaceDetectedException.class);
        }
        catch(net.gdface.sdk.thrift.client.ServiceRuntimeException e){
            throw new ServiceRuntimeException(e);
        }
        catch(RuntimeTApplicationException e){
            return net.gdface.thrift.ThriftUtils.returnNull(e);
        }
        finally{
            factory.releaseInstance(instance);
        }
    }
    @Override
    public CodeInfo getCodeInfo(byte[] imgData,
        CodeInfo facePos) 
        {
        net.gdface.sdk.thrift.client.FaceApi instance = delegate();
        try{
            return TypeTransformer.getInstance().to(
                    instance.getCodeInfoSingle(imgData,
                TypeTransformer.getInstance().to(
                    facePos,
                    CodeInfo.class,
                    net.gdface.sdk.thrift.client.CodeInfo.class)),
                    net.gdface.sdk.thrift.client.CodeInfo.class,
                    CodeInfo.class);
        }
        catch(net.gdface.sdk.thrift.client.ServiceRuntimeException e){
            throw new ServiceRuntimeException(e);
        }
        catch(RuntimeTApplicationException e){
            return net.gdface.thrift.ThriftUtils.returnNull(e);
        }
        finally{
            factory.releaseInstance(instance);
        }
    }
    @Override
    public byte[] getFeature(Map<ByteBuffer, CodeInfo> faces) 
        throws NotFaceDetectedException{
        net.gdface.sdk.thrift.client.FaceApi instance = delegate();
        try{
            return instance.getFeature(TypeTransformer.getInstance().to(
                    faces,
                    ByteBuffer.class,
                    CodeInfo.class,
                    byte[].class,
                    net.gdface.sdk.thrift.client.CodeInfo.class));
        }
        catch(net.gdface.sdk.thrift.client.NotFaceDetectedException e){
            throw TypeTransformer.getInstance().to(
                    e,
                    net.gdface.sdk.thrift.client.NotFaceDetectedException.class,
                    NotFaceDetectedException.class);
        }
        catch(net.gdface.sdk.thrift.client.ServiceRuntimeException e){
            throw new ServiceRuntimeException(e);
        }
        catch(RuntimeTApplicationException e){
            return net.gdface.thrift.ThriftUtils.returnNull(e);
        }
        finally{
            factory.releaseInstance(instance);
        }
    }
    @Override
    public boolean hasFace(byte[] imgData) 
        throws ImageErrorException{
        net.gdface.sdk.thrift.client.FaceApi instance = delegate();
        try{
            return instance.hasFace(imgData);
        }
        catch(net.gdface.sdk.thrift.client.ImageErrorException e){
            throw TypeTransformer.getInstance().to(
                    e,
                    net.gdface.sdk.thrift.client.ImageErrorException.class,
                    ImageErrorException.class);
        }
        catch(net.gdface.sdk.thrift.client.ServiceRuntimeException e){
            throw new ServiceRuntimeException(e);
        }
        finally{
            factory.releaseInstance(instance);
        }
    }
    @Override
    public boolean isLocal(){
        return false;
    }
    @Override
    public boolean multiFaceFeature() 
        {
        net.gdface.sdk.thrift.client.FaceApi instance = delegate();
        try{
            return instance.multiFaceFeature();
        }
        catch(net.gdface.sdk.thrift.client.ServiceRuntimeException e){
            throw new ServiceRuntimeException(e);
        }
        finally{
            factory.releaseInstance(instance);
        }
    }
    @Override
    public String sdkVersion() 
        {
        net.gdface.sdk.thrift.client.FaceApi instance = delegate();
        try{
            return instance.sdkVersion();
        }
        catch(net.gdface.sdk.thrift.client.ServiceRuntimeException e){
            throw new ServiceRuntimeException(e);
        }
        catch(RuntimeTApplicationException e){
            return net.gdface.thrift.ThriftUtils.returnNull(e);
        }
        finally{
            factory.releaseInstance(instance);
        }
    }
}